package study.thread.lock;

import java.util.concurrent.CyclicBarrier;

public class BenchmarkTest {

	private Counter counter;
	private CyclicBarrier barrier;
	private int threadNum;
	private int loopNum;
	private String testName;

	public BenchmarkTest(Counter counter, int threadNum, int loopNum,
			String testName) {

		this.counter = counter;
		barrier = new CyclicBarrier(threadNum + 1); // 关卡计数=线程数+1

		this.threadNum = threadNum;
		this.loopNum = loopNum;
		this.testName = testName;
	}

	public static void main(String args[]) throws Exception {
		
		int threadNum = 5000;
		int loopNum = 100;
		
		new BenchmarkTest(new SynchronizedBenchmarkDemo(), threadNum, loopNum,
				"内部锁").test();
		
		new BenchmarkTest(new ReentrantLockUnfairBeanchmarkDemo(), threadNum,
				loopNum, "不公平重入锁").test();
		
		new BenchmarkTest(new ReentrantLockFairBeanchmarkDemo(), threadNum,
				loopNum, "公平重入锁").test();

	}

	public void test() throws Exception {
		try {
			//启动threadNum个线程
			for (int i = 0; i < threadNum; i++) {
				new TestThread(counter, loopNum).start();
			}
			
			long start = System.currentTimeMillis();
			
			//CyclicBarrier类的await()方法：在所有参与者都已经在此 barrier 上调用 await 方法之前，将一直等待。
			
			barrier.await(); // 等待所有任务线程创建,然后通过关卡，统一执行所有线程 
			
			// 等待所有任务计算完成 (如果少了这一句，就会抛出异常java.lang.OutOfMemoryError)
			barrier.await(); 
			
			long end = System.currentTimeMillis();
			System.out.println(this.testName + " count value:"
					+ counter.getValue());
			System.out.println(this.testName + " 花费时间:" + (end - start) + "毫秒");
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	class TestThread extends Thread {
		int loopNum = 100;
		private Counter counter;

		public TestThread(final Counter counter, int loopNum) {
			this.counter = counter;
			this.loopNum = loopNum;
		}

		public void run() {
			try {
				
				// 等待所有的线程开始 
				barrier.await();
				
				for (int i = 0; i < this.loopNum; i++) {
					counter.increment();
				}
				
				// 等待所有的线程完成 
				barrier.await();
			} catch (Exception e) {
				throw new RuntimeException(e);
			}
		}
	}
}
